package com.sf.fy.uav.applet.config;

import com.sf.fy.uav.common.enums.OrderStatusEnum;
import com.sf.fy.uav.common.enums.ServicePrefixEnum;
import com.sf.fy.uav.common.utils.PhoneEncoderUtil;
import com.sf.fy.uav.common.utils.RedisPrefixKey;
import com.sf.fy.uav.order.controller.CityAirportRest;
import com.sf.fy.uav.order.controller.OrderExtraController;
import com.sf.fy.uav.order.entity.CityAirport;
import com.sf.fy.uav.order.entity.OrderExtra;
import com.sf.fy.uav.order.entity.OrderInfo;
import com.sf.fy.uav.order.mapper.OrderInfoMapper;
import com.sf.fy.uav.sms.rest.SendSmsRest;
import com.sf.fy.uav.utils.AirportInfoUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.Set;

/**
 * @author LTQ
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DelayQueue {


    @Value("${redis.dead:delayQueue}")
    private String DELAY_MESSAGE_QUEUE;

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private final RedisTemplate<String, String> redisTemplate;

    @Autowired
    private PhoneEncoderUtil phoneEncoderUtil;

    @Autowired
    private CityAirportRest cityAirportRest;

    @Autowired
    private SendSmsRest sendSmsRest;

    @Autowired
    private AirportInfoUtils airportInfoController;

    @Value("${sms.pending-items-template-code:DING-DAN-CHAO-SHI-WEI-JIE-DAN-TI-XING}")
    private String pendingItemsTemplateCode;

    @Value("${sms.door-to-door-pickup-down-template-code:DING-DAN-CHAO-SHI-WEI-SHANG-MEN-QU-HUO-TI-XING}")
    private String doorToDoorPickupDownTemplateCode;

    @Value("${sms.drone-has-been-picked-up-template-code:DING-DAN-WU-REN-JI-CHAO-SHI-WEI-QI-FEI-TI-XING}")
    private String droneHasBeenPickedUpTemplateCode;
    @Value("${sms.drone-delivery-in-progress-template-code:DING-DAN-WU-REN-JI-CHAO-SHI-WEI-CHU-LI-JIANG-LUO-TI-XING}")
    private String droneDeliveryInProgressTemplateCode;
    @Value("${sms.to-be-dispatched-template-code:DING-DAN-CHAO-SHI-WEI-PAI-SONG-WAN-CHENG-TI-XING}")
    private String toBeDispatchedTemplateCode;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderExtraController orderExtraController;

    /**
     * 消息入队
     * 只要用户继续发起请求，就会继续延长时间戳的时间 直到用户一直没有请求后，然后到达指定时间给消费者进行消费
     * 如果有其他用户进来，那么这个队列会根据时间戳进行排序 排在前面的并且达到指定时间就先进行消费
     *
     * @param msg
     * @param time
     */
    public void pushQueue(String msg, Long time) {
        try {
            // 存的值是集合的主键 一般固定
            // 第二个是id 每个用户一个id
            // 第三个是根据什么进行排序，这里是根据时间戳，这里如果是同个key，那么会刷新同个key的时间戳并重新进行排序
            // 不同的key就是当前时间加10秒，也就是10秒后过期
            log.info("生产了消息" + msg + "生产时间 " + simpleDateFormat.format(System.currentTimeMillis()));
            redisTemplate.opsForZSet().add(ServicePrefixEnum.SAME_CITY + "." + DELAY_MESSAGE_QUEUE, msg, System.currentTimeMillis() + time);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 消息出队
     * 权重就是时间戳
     */
//    @Scheduled(cron = "0/5 * * * * ?")
    public void pullQueue() {
        System.out.println("------------等待消费--------------" + simpleDateFormat.format(System.currentTimeMillis()));
        // 获取0-当前时间戳的范围的所有值
        Set<String> set = redisTemplate.opsForZSet().rangeByScore(ServicePrefixEnum.SAME_CITY + "." + DELAY_MESSAGE_QUEUE, 0, System.currentTimeMillis());
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String value = iterator.next();
            if (value.startsWith(ServicePrefixEnum.SAME_CITY.name())) {
                // 遍历取出每一个score
                Double score = redisTemplate.opsForZSet().score(ServicePrefixEnum.SAME_CITY + "." + DELAY_MESSAGE_QUEUE, value);
                if (!ObjectUtils.isEmpty(score)) {
                    // 达到时间进行消费 当前时间大于
                    if (System.currentTimeMillis() > score) {
                        // 移除该队列的值,避免重复消费
                        redisTemplate.opsForZSet().remove(ServicePrefixEnum.SAME_CITY + "." + DELAY_MESSAGE_QUEUE, value);
                        log.info("消费了" + value + "消费时间 " + simpleDateFormat.format(System.currentTimeMillis()));
                        if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.ORDER_COUNT_DOWN)) {
                        } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.PENDING_ITEMS_DOWN) || value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DOOR_TO_DOOR_PICKUP_DOWN) || value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_HAS_BEEN_PICKED_UP_DOWN) || value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_DELIVERY_IN_PROGRESS_DOWN) || value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.TO_BE_DISPATCHED_DOWN)) {
                            String orderId = "";
                            String templateCode = "";
                            OrderInfo orderInfo = null;
                            if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.PENDING_ITEMS_DOWN)) {
                                orderId = value.replace(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.PENDING_ITEMS_DOWN, "");
                                orderInfo = orderInfoMapper.selectById(orderId);
                                if (!OrderStatusEnum.PENDING_ITEMS.getStatus().equals(orderInfo.getOrderStatus())) {
                                    continue;
                                }
                                templateCode = pendingItemsTemplateCode;
                            } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DOOR_TO_DOOR_PICKUP_DOWN)) {
                                orderId = value.replace(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DOOR_TO_DOOR_PICKUP_DOWN, "");
                                orderInfo = orderInfoMapper.selectById(orderId);
                                if (!OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus().equals(orderInfo.getOrderStatus())) {
                                    continue;
                                }
                                templateCode = doorToDoorPickupDownTemplateCode;
                            } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_HAS_BEEN_PICKED_UP_DOWN)) {
                                orderId = value.replace(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_HAS_BEEN_PICKED_UP_DOWN, "");
                                orderInfo = orderInfoMapper.selectById(orderId);
                                if (!OrderStatusEnum.DRONE_HAS_BEEN_PICKED_UP.getStatus().equals(orderInfo.getOrderStatus())) {
                                    continue;
                                }
                                templateCode = droneHasBeenPickedUpTemplateCode;
                            } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_DELIVERY_IN_PROGRESS_DOWN)) {
                                orderId = value.replace(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_DELIVERY_IN_PROGRESS_DOWN, "");
                                orderInfo = orderInfoMapper.selectById(orderId);
                                if (!OrderStatusEnum.DRONE_DELIVERY_IN_PROGRESS.getStatus().equals(orderInfo.getOrderStatus())) {
                                    continue;
                                }
                                templateCode = droneDeliveryInProgressTemplateCode;
                            } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.TO_BE_DISPATCHED_DOWN)) {
                                orderId = value.replace(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.TO_BE_DISPATCHED_DOWN, "");
                                orderInfo = orderInfoMapper.selectById(orderId);
                                if (!OrderStatusEnum.TO_BE_DISPATCHED.getStatus().equals(orderInfo.getOrderStatus())) {
                                    continue;
                                }
                                templateCode = toBeDispatchedTemplateCode;
                            }

                            OrderExtra orderExtra = orderExtraController.getByOrderId(orderId);
                            if (!ObjectUtils.isEmpty(orderInfo)) {
                                String takeoffConnId = orderInfo.getTakeoffConnId();
                                String landingConnId = orderInfo.getLandingConnId();
                                if (!StringUtils.isEmpty(takeoffConnId) && !StringUtils.isEmpty(landingConnId) && !ObjectUtils.isEmpty(orderExtra)) {
                                    CityAirport takeoffCityAirport = cityAirportRest.selectByConnId(takeoffConnId);
                                    CityAirport landingCityAirport = cityAirportRest.selectByConnId(landingConnId);
                                    String place = "";
                                    String phone = "";
                                    if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.PENDING_ITEMS_DOWN)) {
                                        place = takeoffCityAirport.getName();
                                        phone = orderExtra.getFySenderTel();
                                    } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DOOR_TO_DOOR_PICKUP_DOWN)) {
                                        place = takeoffCityAirport.getName();
                                        phone = orderExtra.getFySenderTel();
                                    } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_HAS_BEEN_PICKED_UP_DOWN)) {
                                        place = takeoffCityAirport.getName();
                                        phone = orderExtra.getFySenderTel();
                                    } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.DRONE_DELIVERY_IN_PROGRESS_DOWN)) {
                                        place = landingCityAirport.getName();
                                        phone = orderExtra.getFyReceiverTel();
                                    } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.TO_BE_DISPATCHED_DOWN)) {
                                        place = landingCityAirport.getName();
                                        phone = orderExtra.getFyReceiverTel();
                                    }
                                    phone = phoneEncoderUtil.decryptString(phone);
                                    sendSmsRest.sendNotice(phone, templateCode, orderInfo.getTcWaybillNo(), place);
                                }
                            }

                        } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.SEND_NOTICE)) {
                        } else if (value.contains(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.RECORD_AIR_PORT)) {
                            String[] longitudeAndLatitude = value.replace(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.RECORD_AIR_PORT, "").split("_");
                            if (longitudeAndLatitude.length == 3) {
                                String uuid = longitudeAndLatitude[0];
                                double longitude = Double.parseDouble(longitudeAndLatitude[1]);
                                double latitude = Double.parseDouble(longitudeAndLatitude[2]);
                                airportInfoController.obtainTheNearestTerminalWithinTheRange(uuid, longitude, latitude);
                            }
                        }
                    }
                }
            }

        }
    }

}

